/*
    libnbds
    Non-blocking Data Structures Library

    Copyright (C) 2011 Paweł Dziepak

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef NBDS_HAZARD_POINTER_H
#define NBDS_HAZARD_POINTER_H

#include <list>

#include "thread_private.h"

namespace nbds {
	class hazard_pointer_base {
	private:
		struct hp_ticket {
			hp_ticket *prev;

			void *ptr;

			std::list<void*> retired;
		};

		hp_ticket *last;
		thread_private<hp_ticket> ticket;

		void (*destr)(void*);

		hp_ticket *get_ticket();
		bool try_retire(void*);
	public:
		hazard_pointer_base(void (*d)(void*)) : last(0), destr(d) { }

		void set(void*);
		void release();

		void retire(void*);
	};

	template<typename T>
	class hazard_pointer : public hazard_pointer_base {
	private:
		static void destructor(void *obj) {
			delete reinterpret_cast<T*>(obj);
		}
	public:
		hazard_pointer() : hazard_pointer_base(destructor) { }
	};
}

#endif
